package dav

import (
	"encoding/json"
	"os"
	"strings"

	"log"
	"path/filepath"

	"github.com/studio-b12/gowebdav"
)

type DavSync struct {
	client   *gowebdav.Client
	Del_flag bool
}

func New(davUrl string, davUsername string, davPassword string) (_davSync *DavSync) {
	// 创建WebDAV客户端
	davSync := DavSync{}
	davSync.client = gowebdav.NewClient(davUrl, davUsername, davPassword)
	return &davSync
}

func (davSync *DavSync) Upload(localFilePath string, webdavFilePath string) (err error) {

	bytes, _ := os.ReadFile(localFilePath)

	err = davSync.client.Write(webdavFilePath, bytes, 0644)
	// 检查错误信息中是否包含指定字符串
	if err != nil && strings.Contains(err.Error(), "403") {
		_newDir := strings.ReplaceAll(filepath.Dir(webdavFilePath), "\\", "/")
		if _newDir != "" {
			log.Println("目录可能不存在，重试一次 " + _newDir)
			davSync.client.MkdirAll(_newDir, 0755)
			err = davSync.client.Write(webdavFilePath, bytes, 0644)
		}

	}
	return err
}
func (davSync *DavSync) getInfo(path string) os.FileInfo {
	f, _err := davSync.client.Stat(path)
	if _err != nil {
		return nil
	}
	return f
}

// ListFilesRecursively 遍历指定目录下的所有文件，并返回完整的文件路径数组
func listFilesRecursively(dir string) ([]string, error) {
	var files []string

	err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if !info.IsDir() {
			files = append(files, path)
		}
		return nil
	})

	if err != nil {
		return nil, err
	}

	return files, nil
}

func readDat(filePath string) map[string]interface{} {
	data, _ := os.ReadFile(filePath)
	var jsonData = make(map[string]interface{})
	json.Unmarshal(data, &jsonData)
	return jsonData
}

// writeJSONToFile 将 map[string]interface{} 参数转换为 JSON 字符串，并写入指定文件中。
// 该函数接收一个 map[string]interface{} 类型的数据和一个文件路径作为参数，
// 将数据转换为 JSON 格式并写入指定的文件。
// 参数:
//
//	data map[string]interface{}: 需要转换为 JSON 的数据。
//	filePath string: 写入 JSON 数据的文件路径。
//
// 返回值:
//
//	error: 如果写入文件过程中发生错误，返回相应的错误信息；否则返回 nil。
func writeDat(data map[string]interface{}, filePath string) error {
	// 将 map[string]interface{} 转换为 JSON 字符串
	jsonData, err := json.MarshalIndent(data, "", "    ")
	if err != nil {
		return err
	}

	// 将 JSON 字符串写入指定文件
	err = os.WriteFile(filePath, jsonData, 0644)
	if err != nil {
		return err
	}

	return nil
}

func (davSync *DavSync) Sync(localPath string, davPath string) {

	if davPath != "" {
		davPath = davPath + "/"
	}

	// 指定上传根目录
	root := localPath
	// 遍历目录，生成带上传文件路径数组
	files, _err := listFilesRecursively(root)
	log.Println(_err)

	dat := readDat("./upload.txt")
	for _, file := range files {
		log.Println(file)
		if info, ok := dat[file]; !ok {
			log.Println("上传 " + file)

			_davPath := davPath + strings.ReplaceAll(file, "\\", "/")
			// 检查远程文件是否存在
			if davSync.Del_flag {
				log.Println("删除标志已开启")
				dav_fileinfo := davSync.getInfo(_davPath)
				if dav_fileinfo != nil {
					log.Println("文件存在 删除" + file)
					log.Println(dav_fileinfo)
					davSync.client.Remove(_davPath)
				}
			}

			err := davSync.Upload(file, _davPath)
			if err != nil {
				log.Println("上传失败 " + file)
				log.Println(err)

			} else {
				log.Println("上传成功 " + file)
				dat[file] = map[string]interface{}{
					"status": "已上传",
					"sfff":   "已上传",
				}
			}

		} else {
			log.Println(info)

		}
	}
	// 存储状态
	writeDat(dat, "./upload.txt")
}
